﻿using System;
using System.Collections.Generic;
using System.Linq;
using QDT.Common.Finance;
using QDT.Core.Assignments;
using QDT.Core.Deals;
using QDT.Core.Projects;

namespace QDT.Services.Projects
{
    public class MonthRepaymentStrategy : IRepayStrategy
    {
        //public MonthRepaymentStrategy(Project project)
        //{

        //    Check.Argument.IsNotNull(project, "project");

        //    if(project.Status!=ProjectStatus.Repaying&&project.Status!=ProjectStatus.Repaid) throw new Exception("Project 状态无效，必须处于还款中或者还款完成的项目才能计算还款模型.");
        //    if (project.SuccessTime == null) throw new Exception("Project 成功的时间为Null,不能计算还款模型");

        //    StartDate = project.SuccessTime.Value;
        //    Month = project.RepayTime;
        //    BorrowMoney = project.BorrowAmount;
        //    AnnualRate = project.Rate;
        //}

        public MonthRepaymentStrategy(DateTime start,int month,double annualRate,decimal money) {

            if (money <= 0) throw new ArgumentException("money 必须是大于0的数");

            StartDate = start;
            Month = month;
            AnnualRate = annualRate;
            Money = money;
        }

        /// <summary>
        /// 还款记录
        /// </summary>
        public IList<CreditRepayment> Records { get; set; }

        /// <summary>
        /// 开始日期
        /// </summary>
        public virtual DateTime StartDate { get; private set; }

        /// <summary>
        /// 借款期限（月份）
        /// </summary>
        public virtual int Month { get; private set; }

        /// <summary>
        /// 年化率
        /// </summary>
        public virtual double AnnualRate { get; private set; }

        /// <summary>
        /// 借款金额
        /// </summary>
        public decimal Money { get; private set; }

        /// <summary>
        /// 计算月利息
        /// </summary>
        /// <param name="money"></param>
        /// <returns></returns>
        protected virtual decimal GetInterest(decimal money) {
            return InterestAlgorithm.MonthInterest(money, AnnualRate);
        }

        /// <summary>
        /// 按月份的形式计算每期还款时间
        /// </summary>
        /// <param name="stage"></param>
        /// <returns></returns>
        protected virtual DateTime ReplayTimeOfCycle(int stage)
        {
            //提前发放利息，有问题（2014-3-10）
            stage -= 1;

            var replyTime = StartDate.AddMonths(stage);

            var d = StartDate.Day;

            //解决29，30，31计算下一个月出现的问题
            var endDay = DateTime.DaysInMonth(replyTime.Year, replyTime.Month);

            if (d > endDay) d = endDay;

            return new DateTime(replyTime.Year, replyTime.Month, d);
        }

        #region Implementation of IRepaymentStrategy

        /// <summary>
        /// 获得还款计划表
        /// </summary>
        /// <returns>还款计划表</returns>
        public RepaymentScheme GetRepayTableForProject(IList<DebtorRepayment> repayments)
        {

            var models = new List<RepaymentStage>();

            for (var i = 1; i <= Month; i++)
            {
                var model = new RepaymentStage(i,ReplayTimeOfCycle(i),GetInterest(Money),0,"利息"){RepayType = 1};

                UpdateStage(repayments,model);

                models.Add(model);
            }

            //最后一期为偿还本金期
            var endStage = Month+1;

            var endModel = new RepaymentStage(endStage, ReplayTimeOfCycle(endStage).AddDays(-1), 0, Money, "本金")
                {
                                                                                                                 RepayType = 2,
                                                                                                                 IsLast = true
                                                                                                             };
            UpdateStage(repayments,endModel);

            models.Add(endModel);

            return new RepaymentScheme(models);
        }

        /// <summary>
        /// 通过债权获得本债权的回款计划
        /// </summary>
        /// <param name="credit">债权，此债权必须是当前项目的债权</param>
        /// <returns></returns>
        public RepaymentScheme GetCreditRepaymenScheme(Credit credit) {
            
            var models = new List<RepaymentStage>();

            for (var i = 1; i <= Month; i++)
            {
                var model = new RepaymentStage(i, ReplayTimeOfCycle(i), GetInterest(credit.Money), 0, "利息") { RepayType = 1 };

                UpdateStage(credit.Repayments, model);

                models.Add(model);
            }

            //最后一期为偿还本金期
            var endStage = Month + 1;

            var endModel = new RepaymentStage(endStage, ReplayTimeOfCycle(endStage).AddDays(-1), 0, credit.Money, "本金")
            {
                RepayType = 2,
                IsLast = true
            };
            UpdateStage(credit.Repayments, endModel);

            models.Add(endModel);

            return new RepaymentScheme(models);
        }

        public RepaymentScheme GetCreditRepaymenScheme(Credit credit, Credit sellerCredit)
        {
            throw new NotImplementedException();
        }

        public RepaymentScheme GetAssignmentRepaymenScheme(Assignment assignment)
        {
            throw new Exception("此类型不允许债权转让");
        }

        /// <summary>
        /// 通过债权创建债权转让信息对象
        /// </summary>
        /// <param name="credit"></param>
        /// <param name="feeRate"> </param>
        /// <param name="discountRate"> </param>
        /// <returns></returns>
        public Assignment CreateAssignment(Credit credit, double feeRate, double discountRate)
        {
            throw new Exception("此类型不允许债权转让");
        }

        public Assignment CreateAssignment(Credit credit, decimal money, double feeRate, double discountRate, bool isOffline)
        {
            throw new Exception("此类型不允许债权转让");
        }

        public bool IsAssignment {
           get { return false; }
        }

        /// <summary>
        /// 偿还债权
        /// </summary>
        /// <param name="credit">债权</param>
        /// <param name="stage">期次</param>
        public void RepayCredit(Credit credit, int stage) {

            var scheme = GetCreditRepaymenScheme(credit);

            var isRepay = scheme[stage].IsRepay;

            if(isRepay) return;

            var rempayment = new CreditRepayment {
                                                         CreditId = credit.ID,
                                                         RepayMoney = scheme[stage].Ammount,
                                                         RepayTime = scheme[stage].Time,
                                                         TrueRepayTime = DateTime.Now
                                                     };

            credit.Repayments.Add(rempayment);

        }

        private void UpdateStage(IEnumerable<CreditRepayment> repayments, RepaymentStage stage)
        {

            if (repayments == null) return;

            var record = repayments.FirstOrDefault(x => x.RepayTime.Date == stage.Time.Date);

            if (record != null)
            {
                stage.IsRepay = true;
                stage.ActualTime = record.TrueRepayTime;
            }
        }

        private void UpdateStage(IEnumerable<DebtorRepayment> repayments,RepaymentStage stage)
        {

            if (repayments == null) return;

            var record = repayments.FirstOrDefault(x => x.RepayTime.Date == stage.Time.Date);

            if (record != null)
            {
                stage.IsRepay = true;
                stage.ActualTime = record.TrueRepayTime;
            }
        }

        #endregion
    }
}
